#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "parse_code.h"
#include "map.h"
void P_output(int num, Value * base){
    while (num > 0)
    {
        switch (base->type) {
            case DATA_TYPE_BOOLEAN:
                printf("printf: DATA_TYPE_BOOLEAN\n");
            break;
            case DATA_TYPE_NUMBER:
                printf("%.0f", base->entity->number);
            break;
            case DATA_TYPE_STRING:
                printf("%s", base->entity->string);
            break;
            case DATA_TYPE_FUNC:
                printf("outType: DATA_TYPE_FUNC\n");
            break;
            case DATA_TYPE_SYSTEM_FUNC:
                printf("outType: DATA_TYPE_SYSTEM_FUNC\n");
            break;
            case DATA_TYPE_NULL:
                printf("outType: DATA_TYPE_NULL\n");
            break;
        }
        base++;
        num--;
    }

    printf("\n");
    
}
int P_empty(Value *val){
    if(val->type == DATA_TYPE_NULL) return 1;
    
    //TODO 当where条件时, 有bug  例如: c=0;c<n
    //if(val->entity->number == 0) return 1;

    return 0;
}


DataType codeTypeTodataType(OpCode type){
    switch (type)
    {
        case RET_ARR_NUM: return DATA_TYPE_NUMBER;
        case RET_ARR_STR: return DATA_TYPE_STRING;
        case RET_ARR_BOOL: return DATA_TYPE_BOOLEAN;
        case RET_NUM: return DATA_TYPE_NUMBER;
        case RET_STR: return DATA_TYPE_STRING;
        case RET_BOOL: return DATA_TYPE_BOOLEAN;
    }
    
}
/*
DataType transformType(DataType type){
    switch (type)
    {
        case DATA_TYPE_BOOLEAN: return DATA_TYPE_ARRAY_BOOLEAN;
        case DATA_TYPE_NUMBER: return DATA_TYPE_ARRAY_NUMBER;
        case DATA_TYPE_STRING: return DATA_TYPE_ARRAY_STRING;
        case DATA_TYPE_FUNC: return DATA_TYPE_ARRAY_FUNC;
    }
}
*/

Entity * GetEntityMemory(){
    return (Entity*)malloc(sizeof(Entity));
}

Value * GetValueMemory(){
    Value * tmp = (Value*)malloc(sizeof(Value));
    tmp->entity = GetEntityMemory();
    tmp->attr = ATTR_VAR;
    tmp->length = 1;
    tmp->backup_array = tmp;
    return tmp;
}

UserFunc * GetFuncMemory(){
    return (UserFunc*)malloc(sizeof(UserFunc));
}

Value *SetUserFunction(char *name, Byte *bp, Word c){
    Value *func = GetValueMemory();
    func->name=name;
    func->type=DATA_TYPE_FUNC;
    func->entity->user_func= GetFuncMemory();
    func->entity->user_func->content = bp;
    func->entity->user_func->content_length = c;
    return func;
}

void console_error(char * e){
    printf("\033[31;1mERROR:\e[0m");
    printf("%s \n", e);
    exit(0);
}


int EntityAssignment(Entity *left, Entity *right, DataType  type){
    switch (type)
    {
        case DATA_TYPE_BOOLEAN: left->boolean = right->boolean;break;
        case DATA_TYPE_NUMBER: left->number = right->number;break;
        case DATA_TYPE_STRING: left->string = right->string;break;
        case DATA_TYPE_FUNC: left->user_func = right->user_func;break;
        case DATA_TYPE_SYSTEM_FUNC: left->system_func = right->system_func;break;
    }

    return 1;
}

int assignment(Value *left, Value *right, int free){
    if(free == 1){ // 无条件赋值
        left->entity = right->entity;
        left->attr = right->attr;
        left->length = right->length;
        left->array = right->array;
        left->backup_array = right->backup_array;
    }else if(right->attr == ATTR_CONSTANT){

        if(left->attr != ATTR_ARRAY_DATA && left->attr != ATTR_VAR) console_error("ATTR_CONSTANT assignment error!!!");
        EntityAssignment(left->entity, right->entity, left->type);

    }else if(right->attr == ATTR_VAR){

        if(left->attr != ATTR_VAR && left->attr != ATTR_ARRAY_DATA) console_error("ATTR_VAR assignment error!!!");
        EntityAssignment(left->entity, right->entity, left->type);

    }else if(right->attr == ATTR_ARRAY){

        if(left->attr != ATTR_ARRAY ) console_error("ATTR_ARRAY assignment error!!!");
        if(left->length != right->length ) console_error("ATTR_ARRAY length assignment error!!!");
        // top
        left->array = right->array;
        // var
        left->backup_array->array = right->array;

        left->attr = right->attr;
        left->length = right->length;
    }else if(right->attr == ATTR_ARRAY_DATA){

        if(left->attr == ATTR_ARRAY_DATA && left->length == right->length){
            // top
            left->entity = right->entity;
            
            // var
            left->backup_array->entity = right->entity;

            left->attr = right->attr;
            left->length = right->length;
        }else if(left->attr == ATTR_VAR){
            EntityAssignment(left->entity, right->entity, left->type);
        }else{
            console_error("ATTR_ARRAY_DATA assignment error!!!");
        }

    }else{
        return 0;
    }
    return 1;
}


void createArray(Word now_l,Word layer, Value *source, Word *layer_count){

    if(now_l == layer){
        source->length = layer_count[now_l];
        source->entity = (Entity *)calloc(source->length, sizeof(Entity) );
        source->attr = ATTR_ARRAY_DATA;
    }else{
        for(Word i=0; i<=layer; i++){
            source->length = layer_count[now_l];
            source->array = (Value *)calloc(source->length,sizeof(Value) );
            source->attr = ATTR_ARRAY;
            for(Word j=0; j<source->length;j++){
                source->array[j].type = source->type;
                source->array[j].backup_array = &(source->array[j]);
                createArray(now_l+1, layer, &(source->array[j]), layer_count);
            }
        }
    }
}

Value * getArray(){
    
}

int is_array(const Value *source){
    int ret = 0;
    if(source && source->attr == ATTR_ARRAY || source->length >1) ret = 1;
    return ret;
}